import { createUUID } from 'qx-util';
import { isNil } from 'ramda';
import {
  ValueOP,
  CodeListItem,
  KanbanController,
  MDCtrlLoadParams,
  IMDControlGroupState,
} from '@ibiz-template/runtime';
import { IPanel } from '@ibiz/model-core';
import { IOdooKanbanSwimlane, IOdooSwimlaneKanbanState } from './interface';

/**
 * @description odoo泳道看板
 * @export
 * @class OdooSwimlaneKanbanController
 * @extends {KanbanController}
 */
export class OdooSwimlaneKanbanController extends KanbanController {
  /**
   * @description odoo泳道看板UI状态
   * @type {IOdooSwimlaneKanbanState}
   * @memberof OdooSwimlaneKanbanController
   */
  declare state: IOdooSwimlaneKanbanState;

  /**
   * @description 初始化State
   * @protected
   * @memberof OdooSwimlaneKanbanController
   */
  protected initState(): void {
    super.initState();
    this.state.activities = [];
  }

  /**
   * @description 根据id获取布局面板
   * @param {string} id
   * @returns {*}  {(IPanel | undefined)}
   * @memberof OdooSwimlaneKanbanController
   */
  getLayoutPanelById(id: string): IPanel | undefined {
    return this.model.controlRenders?.find(
      render => render.renderType === 'LAYOUTPANEL' && render.id === id,
    )?.layoutPanel;
  }

  /**
   * @description 部件加载后处理
   * @param {MDCtrlLoadParams} args
   * @param {IData[]} items
   * @returns {*}  {Promise<IData[]>}
   * @memberof OdooSwimlaneKanbanController
   */
  async afterLoad(args: MDCtrlLoadParams, items: IData[]): Promise<IData[]> {
    this.state.activities = await this.loadActiveData();
    await this.handleActiveGroup();
    await this.handleActiveSwimlane();
    return items;
  }

  /**
   * @description 加载活动数据
   * @returns {*}  {Promise<IData[]>}
   * @memberof OdooSwimlaneKanbanController
   */
  async loadActiveData(): Promise<IData[]> {
    const { fetchcontrolaction } = this.controlParams;
    if (!fetchcontrolaction) return [];
    const app = ibiz.hub.getApp(this.context.srfappid);
    const result = await app.deService.exec(
      `${this.model.appId.split('__')[1]}.mail_activity`,
      fetchcontrolaction,
      this.context,
      {
        page: 0,
        size: 1000,
        searchconds: [
          {
            condtype: 'GROUP',
            condop: 'AND',
            searchconds: [
              {
                condtype: 'DEFIELD',
                condop: ValueOP.EQ,
                fieldname: 'res_model',
                value: 'hr_employee',
              },
              {
                condtype: 'DEFIELD',
                condop: ValueOP.IN,
                fieldname: 'res_id',
                value: this.state.items.map(item => item.srfkey).join(','),
              },
            ],
          },
        ],
      },
    );
    return result.data as IData[];
  }

  /**
   * @description 处理活动分组
   * @returns {*}  {Promise<void>}
   * @memberof OdooSwimlaneKanbanController
   */
  async handleActiveGroup(): Promise<void> {
    const { groupappdefieldid, groupcodelistid } = this.controlParams;
    if (!groupappdefieldid) return;
    const groupMap: Map<string | number, IData[]> = new Map();
    let codeList: readonly CodeListItem[] = [];
    if (groupcodelistid) {
      const app = ibiz.hub.getApp(this.context.srfappid);
      codeList = await app.codeList.get(
        groupcodelistid,
        this.context,
        this.params,
      );
      codeList.forEach(item => groupMap.set(item.value, []));
    }
    const { activities } = this.state;
    const unclassified: IMDControlGroupState = {
      key: createUUID(),
      caption: ibiz.i18n.t('runtime.controller.common.md.unclassified'),
      children: [],
    };
    activities.forEach((item: IData) => {
      // 如果有外键值文本属性，则根据外键值文本属性分组
      const groupVal = item[groupappdefieldid];
      // 分组无值默认归为未分类
      if (isNil(groupVal)) {
        unclassified.children.push(item);
      } else {
        const children = groupMap.get(groupVal) || [];
        children.push(item);
        groupMap.set(groupVal, children);
      }
    });
    const groups: IMDControlGroupState[] = [];
    groupMap.forEach((value: IData[], key: string | number) => {
      const codeListItem = codeList.find(x => x.value === key);
      groups.push({
        key,
        caption: codeListItem?.text || (key as string),
        children: value,
      });
    });
    // 将未分类放到最后
    if (unclassified.children.length) groups.push(unclassified);
    this.state.groups = groups;
  }

  /**
   * @description 处理活动泳道
   * @returns {*}  {Promise<void>}
   * @memberof OdooSwimlaneKanbanController
   */
  async handleActiveSwimlane(): Promise<void> {
    const { swimlaneappdefieldid, swimlanecodelistid } = this.controlParams;
    if (!swimlaneappdefieldid) return;
    const { activities } = this.state;
    let swimlanes: IOdooKanbanSwimlane[] = [];
    const unclassified: IOdooKanbanSwimlane = {
      count: 0,
      key: undefined,
      isExpand: true,
      caption: ibiz.i18n.t('runtime.controller.common.md.unclassified'),
    };
    if (swimlanecodelistid) {
      const app = ibiz.hub.getApp(this.context.srfappid);
      const codeListItems = await app.codeList.get(
        swimlanecodelistid,
        this.context,
        this.params,
      );
      swimlanes = codeListItems.map(item => {
        return {
          count: 0,
          data: item,
          isExpand: true,
          caption: item.text,
          key: item.value?.toString(),
        };
      });
      activities.forEach(item => {
        const lane = swimlanes.find(
          l => l.key === item[swimlaneappdefieldid]?.toLowerCase(),
        );
        if (lane) lane.count += 1;
      });
    } else {
      activities.forEach(item => {
        if (item[swimlaneappdefieldid]) {
          const lane = swimlanes.find(
            l => l.key === item[swimlaneappdefieldid],
          );
          if (lane) {
            lane.count += 1;
          } else {
            swimlanes.push({
              count: 1,
              isExpand: true,
              key: item[swimlaneappdefieldid],
              caption: item[swimlaneappdefieldid],
            });
          }
        } else {
          // 没有值的加入到未分类中
          unclassified.count += 1;
        }
      });
    }
    // 将未分类移动到最后
    if (unclassified.count) swimlanes.push(unclassified);
    this.state.swimlanes = swimlanes;
  }
}
